<chapter xml:id="readonly_cstring.h">
<title><tt>__vic/readonly_cstring.h</tt></title>

<chapter xml:id="readonly_cstring">
<title><tt>readonly_cstring</tt></title>

<code-block lang="C++"><![CDATA[
class readonly_cstring
{
public:
    readonly_cstring();
    readonly_cstring(const char *str);
    readonly_cstring(const char *begin, const char *end);
    readonly_cstring(const char *chars, size_t n);
    readonly_cstring(const readonly_cstring &str);
    ~readonly_cstring() noexcept;

    // BEGIN C++11
    readonly_cstring(readonly_cstring &&str) noexcept;
    readonly_cstring &operator=(readonly_cstring &&str) noexcept;
    // END C++11

    readonly_cstring &operator=(const char *str);
    readonly_cstring &operator=(const readonly_cstring &str);
    readonly_cstring &assign(const char *str);
    readonly_cstring &assign(const char *chars, size_t n);
    readonly_cstring &assign(const char *begin, const char *end);

    bool empty() const;
    const char *c_str() const;
    operator const char*() const;

    char *reserve(size_t n);
    void swap(readonly_cstring &str) noexcept;
};

int compare(const readonly_cstring &s1, const readonly_cstring &s2);
int compare(const readonly_cstring &s1, const char *s2);
int compare(const char *s1, const readonly_cstring &s2);

bool operator==(const readonly_cstring &s1, const readonly_cstring &s2);
bool operator!=(const readonly_cstring &s1, const readonly_cstring &s2);
bool operator<(const readonly_cstring &s1, const readonly_cstring &s2);
bool operator>(const readonly_cstring &s1, const readonly_cstring &s2);
bool operator<=(const readonly_cstring &s1, const readonly_cstring &s2);
bool operator>=(const readonly_cstring &s1, const readonly_cstring &s2);

bool operator==(const readonly_cstring &s1, const char *s2);
bool operator!=(const readonly_cstring &s1, const char *s2);
bool operator<(const readonly_cstring &s1, const char *s2);
bool operator>(const readonly_cstring &s1, const char *s2);
bool operator<=(const readonly_cstring &s1, const char *s2);
bool operator>=(const readonly_cstring &s1, const char *s2);

bool operator==(const char *s1, const readonly_cstring &s2);
bool operator!=(const char *s1, const readonly_cstring &s2);
bool operator<(const char *s1, const readonly_cstring &s2);
bool operator>(const char *s1, const readonly_cstring &s2);
bool operator<=(const char *s1, const readonly_cstring &s2);
bool operator>=(const char *s1, const readonly_cstring &s2);

void swap(readonly_cstring &s1, readonly_cstring &s2) noexcept;
]]></code-block>

<p>The simple non-mutable null-terminated string class with automatic memory
management. Has simple and predictable structure that can be useful when
ABI compatibility/stability is required or when usage of <tt>std::string</tt>
is objectionable for some reason. The functionality provided by the class is
also minimal. It provides string copying and storing and read access to it.
One cannot modify string parts - only replace the whole value.</p>

<p>If one need to store a string value in a class, usage of this class may be a
good choice. It's easier-to-use, more clear and safer than array of chars
(<tt>char[]</tt>) and can be more efficient than <tt>std::string</tt>,
though, of course, less universal. If modifications of the string parts are
expected, usage of another string class should be considered, for instance,
<tt>__vic::string_buffer</tt>. Class <tt>readonly_cstring</tt> is not designed
for such purposes.</p>

<section><title>Guarantees provided by the class design</title>
<list style="bulleted">
    <item>Null pointer value is treated as an empty string.</item>
    <item>Cast to C-string (<tt>const char *</tt>) always returns valid
        pointer, never <tt>nullptr</tt>.</item>
    <item>For each string value, exact amount of memory is allocated. No extra
        memory reserved.</item>
    <item>Class contains single data member - pointer to the holded string,
        so the total object's size is likely one pointer.</item>
</list>
</section>

<section><title>Class members</title>

<synopsis>
<prototype>readonly_cstring()</prototype>
<p>Creates an empty string.</p>
<postcondition><tt>empty() == true</tt></postcondition>
</synopsis>

<synopsis>
<prototype>readonly_cstring(const char *str)</prototype>
<prototype>readonly_cstring(const readonly_cstring &amp;str)</prototype>
<p>Creates a copy of <tt>str</tt>.</p>
</synopsis>

<synopsis>
<prototype>readonly_cstring(const char *chars, size_t n)</prototype>
<prototype>readonly_cstring(const char *begin, const char *end)</prototype>
<p>Creates a string from characters range.</p>
</synopsis>

<synopsis>
<prototype>readonly_cstring &amp;operator=(const char *str)</prototype>
<prototype>readonly_cstring &amp;operator=(const readonly_cstring &amp;str)</prototype>
<prototype>readonly_cstring &amp;assign(const char *str)</prototype>
<p>Assigns <tt>str</tt>.</p>
</synopsis>

<synopsis>
<prototype>readonly_cstring(readonly_cstring &amp;&amp;str) noexcept <badge>C++11</badge></prototype>
<prototype>readonly_cstring &amp;operator=(readonly_cstring &amp;&amp;str) noexcept <badge>C++11</badge></prototype>
<p>Move operations for C++11 mode.</p>
</synopsis>

<synopsis>
<prototype>readonly_cstring &amp;assign(const char *begin, const char *end)</prototype>
<prototype>readonly_cstring &amp;assign(const char *chars, size_t n)</prototype>
<p>Assigns the string constructed from characters range.</p>
</synopsis>

<synopsis>
<prototype>bool empty() const</prototype>
<p>Returns <tt>true</tt> if string is empty.</p>
</synopsis>

<synopsis>
<prototype>const char *c_str() const</prototype>
<prototype>operator const char*() const</prototype>
<p>Returns a pointer to the stored string. The pointer is never null.</p>
</synopsis>

<synopsis>
<prototype>char *reserve(size_t n)</prototype>
<p>Allocates internal buffer for <tt>n</tt> chars and returns the pointer to
it. Can be useful in conjunction with functions like <tt>std::sprintf()</tt>.</p>
<note>Try to avoid this unsafe function!</note>
</synopsis>

<synopsis>
<prototype>void swap(readonly_cstring &amp;str) noexcept</prototype>
<p>Swaps the value with <tt>str</tt>.</p>
</synopsis>

</section>

<section><title>Free functions</title>

<synopsis>
<prototype>int compare(const readonly_cstring &amp;s1, const readonly_cstring &amp;s2)</prototype>
<prototype>int compare(const readonly_cstring &amp;s1, const char *s2)</prototype>
<prototype>int compare(const char *s1, const readonly_cstring &amp;s2)</prototype>
<p>Compares two strings as <tt>std::strcmp</tt> does.</p>
</synopsis>

<synopsis>
<prototype>bool operator==(const readonly_cstring &amp;s1, const readonly_cstring &amp;s2)</prototype>
<prototype>...</prototype>
<prototype>bool operator>=(const char *s1, const readonly_cstring &amp;s2)</prototype>
<p>Full set of comparators for <tt>readonly_cstring</tt> and <tt>const char *</tt>
in all combinations.</p>
</synopsis>

<synopsis>
<prototype>void swap(readonly_cstring &amp;s1, readonly_cstring &amp;s2) noexcept</prototype>
<p>Specialization of the standard algorithm.</p>
</synopsis>

</section>

<section><title>Example</title>
<code-block lang="C++">
class C
{
    __vic::readonly_cstring st;
public:
    explicit C(const char *str) : st(str) {}
    const char *get_str() const { return st; }
};
</code-block>
</section>

</chapter>

</chapter>
